#include <stdlib.h>
#include <strings.h>
#include <stdio.h>
#include <strophe.h>
#include <stdarg.h>
#include <unistd.h>

/** 
 * low cost logging code
 **/
#define LOGDIR "/tmp"
static FILE* log_file = NULL;
static FILE* logger_init() {
    	log_file = fopen(LOGDIR "/gcpd.log", "a");
	setbuf(log_file, NULL);
	return log_file;
}

static int logger_close() {
	fclose(log_file);
}

static int logger_log(char *fmt, ...) {
	int result;
	va_list args;
	va_start(args, fmt);
	result = vfprintf(log_file, fmt, args);
	va_end(args);
	return result;
}

void my_logger(void * const userdata, const xmpp_log_level_t level,
               const char * const area, const char * const msg)
{
    if (strcmp((char *)userdata, "gcpd") == 0 && level == XMPP_LEVEL_DEBUG) {
        logger_log("%s\n", msg);
    }
}


int message_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
        printf("print request received\n");
	xmpp_ctx_t *ctx = (xmpp_ctx_t*)userdata;

	if(!xmpp_stanza_get_child_by_name(stanza, "push")) return 1;
	if(!strcmp(xmpp_stanza_get_attribute(stanza, "from"), "cloudprint.google.com")) return 1;

	return 1;
}

void conn_handler(xmpp_conn_t * const conn, const xmpp_conn_event_t status, 
		  const int error, xmpp_stream_error_t * const stream_error,
		  void * const userdata)
{
    xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;

    if (status == XMPP_CONN_CONNECT) {
	xmpp_stanza_t *subscribe, *item, *envelop;
	logger_log("DEBUG: connected\n");
	xmpp_handler_add(conn,message_handler, NULL, "message", NULL, ctx);

	const char *jid = xmpp_conn_get_jid(conn);
	const char *fjid = xmpp_conn_get_bound_jid(conn);
	envelop = xmpp_stanza_new(ctx);
	xmpp_stanza_set_name(envelop, "iq");
	xmpp_stanza_set_attribute(envelop, "from", fjid);
	xmpp_stanza_set_attribute(envelop, "to", jid);
	xmpp_stanza_set_attribute(envelop, "type", "set");
	xmpp_stanza_set_attribute(envelop, "id", "1");

	subscribe = xmpp_stanza_new(ctx);
	xmpp_stanza_set_name(subscribe, "subscribe");
	xmpp_stanza_set_attribute(subscribe, "xmlns", "google:push");
	xmpp_stanza_add_child(envelop, subscribe);

        item = xmpp_stanza_new(ctx);
	xmpp_stanza_set_name(item, "item");
	xmpp_stanza_set_attribute(item, "channel", "cloudprint.google.com");
	xmpp_stanza_set_attribute(item, "from", "cloudprint.google.com");
	xmpp_stanza_add_child(subscribe, item);

        char *dbg;
        size_t len;
        xmpp_stanza_to_text(envelop, &dbg, &len);
        logger_log("%s", dbg);
        free(dbg);

	xmpp_send(conn, envelop);
	xmpp_stanza_release(envelop);
    }
    else {
	logger_log("DEBUG: disconnected\n");
	xmpp_stop(ctx);
    }
}


int main(int argc, char** argv) {
	pid_t pid, sid;
	int retval;
	xmpp_ctx_t	*xmpp_ctx;
 	xmpp_conn_t	*xmpp_con;
        xmpp_log_t	 xmpp_log;

	xmpp_log.handler = my_logger;
        xmpp_log.userdata = "gcpd";

	if (0) {
		/* fork the parent process */
		pid = fork();
		if (pid < 0) {
			exit(EXIT_FAILURE);
		}

		/* if the pid is good then we can exit the parent process. */
		if (pid > 0) {
			fprintf(stderr, "Running as a daemon\n");
			exit(EXIT_SUCCESS);
		}

		/* this is the daemon child process. */
		umask(0);

		/* avoid becomign an orphan */
		sid = setsid();
		if (sid < 0) {
			exit(EXIT_FAILURE);
		}

		/* chdir to safety */
		if((chdir("/")) < 0) {
			exit(EXIT_FAILURE);
		}

		close(STDIN_FILENO);
		close(STDOUT_FILENO);
		close(STDERR_FILENO);
 	}
	/* setup the log file. */
	logger_init();
	char auth[1028];
	FILE* f = fopen("./.cloudprint.auth", "r");
        if (f) {
		fgets(auth, sizeof(auth), f);
		fgets(auth, sizeof(auth), f);
		fclose(f);
	}

	xmpp_initialize();
        xmpp_ctx = xmpp_ctx_new(NULL, &xmpp_log);
	xmpp_con = xmpp_conn_new(xmpp_ctx);

        if(!xmpp_con) {
		exit(1);
	}

	xmpp_conn_set_jid(xmpp_con, argv[1]);
	xmpp_conn_set_pass(xmpp_con, argv[2]);
	xmpp_conn_set_auth_token(xmpp_con, auth);

	//connect to the server
	retval = xmpp_connect_client( xmpp_con, "talk.google.com", 
						0, conn_handler, xmpp_ctx);

	xmpp_run(xmpp_ctx);

	xmpp_conn_release(xmpp_con);
	xmpp_ctx_free(xmpp_ctx);
        xmpp_shutdown();
	logger_close();
}
